#include "MainWindow.h"
#include "ConfigureDialog.h"

BBS * bbsServer = 0;

MainWindow::MainWindow(QWidget * parent):QMainWindow(parent)
{
    DEBUG_F();
    setupUi(this);
    createStatusBar();
    createSystrayIcon();
    actionShowList -> setEnabled(false);
    serverModel = new bbsModel(this);
    boardList -> setModel(serverModel);
    boardList -> setAlternatingRowColors(true);
    boardList -> insertAction(0, actionAddFavorite);
    boardList -> insertAction(0, actionShowList);
    readSettings();
    mainProcess();
    connect (&gFastTimer, SIGNAL(timeout()), this, SLOT(updateStatusBar()));
    
}

void MainWindow::on_actionAddFavorite_triggered(){
    DEBUG_F();
    
}
void MainWindow::on_actionShowList_triggered(){
    DEBUG_F();
    Profile * p = bbsModel::index2Profile(boardList->currentIndex());
    if (p == 0) return;
    bool sign = p->getOption("isFavoriteMode");
    p->setOption("isFavoriteMode", !sign);
}
void MainWindow::createSystrayIcon(){
    QMenu * systrayMenu = new QMenu(this);
    QAction * actionWakeup = new QAction(QIcon(":/icon/wakeup.png"), tr("&Wake Up"), this);
    systrayMenu->addAction(actionWakeup);
    systrayMenu->addSeparator();
    systrayMenu->addAction(actionConfigure);
    systrayMenu->addAction(actionQuit);
    SystrayIcon * systrayIcon = SystrayIcon::getSystrayIcon();
    systrayIcon->setContextMenu(systrayMenu);

    connect (actionWakeup, SIGNAL(triggered()), this, SLOT(wakeup()));
    connect (systrayIcon, SIGNAL(clicked (QSystemTrayIcon::ActivationReason)),
	      this, SLOT(systray_clicked(QSystemTrayIcon::ActivationReason)));
}

void MainWindow::wakeup(){
    this->setVisible(true);
    this->show();
}

void MainWindow::on_boardList_pressed(const QModelIndex & index ){
    DEBUG_F();
    Profile * p = bbsModel::index2Profile(index);
    if (p == 0) return;
    actionShowList -> setEnabled(true);
    bool sign = p->getOption("isFavoriteMode");
    if (sign)
	actionShowList -> setText(tr("All boards"));
    else
	actionShowList -> setText(tr("Only Favorite"));
}

void MainWindow::on_boardList_activated(const QModelIndex & index)
{
    DEBUG_F();
    Board * board = bbsModel::index2Board(index);
    if (board == 0)	return;
    ChatDialog * chatDialog = new ChatDialog (board , this);
    chatDialog -> show();
    chatDialog -> raise();
    chatDialog -> activateWindow();
}

void MainWindow::on_actionStart_triggered(){
    foreach(Profile * profile, profiles)
	profile->getBBS()->start();
}

void MainWindow::on_actionStop_triggered(){
    foreach(Profile * profile, profiles)
	profile->getBBS()->stop();
}

void MainWindow::on_actionClose_triggered(){
    hide();
}

void MainWindow::on_actionQuit_triggered(){
    writeSettings();
    qApp->quit();
}

void MainWindow::systray_clicked(QSystemTrayIcon::ActivationReason reason ){
    DEBUG_F();
    int todo = -1;
    bool sign = Options::getGlobalOptions()->getOption("isDoubleClickMode");
    if ((  !sign && (reason == QSystemTrayIcon::Trigger))
	|| (sign && (reason == QSystemTrayIcon::DoubleClick)) ){
	    if (isVisible() == false)
		todo = 0;
	    else
		todo = 1;
    }
    switch (todo){
	case 0:	//wakeup
	    show();
	    raise();
	    activateWindow();
	    break;
	case 1:
	    hide();
	default:
	    break;
    }
}

void MainWindow::createStatusBar(){
    status = new QLabel("");
    status -> setIndent(3);
    statusBar() -> addWidget(status);
    foreach(Profile * profile, profiles)
	connect (profile->getBBS(), SIGNAL(newStatus(int, QString)), this, SLOT(updateStatusBar(int, QString)));
}

void MainWindow::updateStatusBar(int code, QString explain){
    if (code == 104)	// login successful
	writeSettings();
    status->setText(explain);
    boardList->expandAll();
}

void MainWindow::closeEvent(QCloseEvent * /*event*/){
    DEBUG_F();
    static bool sign = true;
    bool stay = Options::getGlobalOptions()->getOption("isStayOnSystray");
    if (stay){
	hide();
	if (sign)    SystrayIcon::getSystrayIcon()->showMessage(tr("Notice"),
			tr("I'm still runing!\nClick here to show the main window."));
	sign = false;
    }
    else
	on_actionQuit_triggered();
}

void MainWindow::writeSettings(){
    DEBUG_F();
    QSettings settings (PROGRAM_COMP, PROGRAM_NAME);
    settings.setValue("MainWindow/geometry", saveGeometry());
    settings.beginGroup("profileList");
    qDebug() << ">> Save Profiles Count =" << profiles.count();
    for(int i = 0; i < profiles.count(); i++){
	profiles[i]->save(settings);
    }
    settings.endGroup();

    settings.beginGroup("Global");
    Options::getGlobalOptions()->save(settings);
    settings.endGroup();
    
}

void MainWindow::readSettings(){
    DEBUG_F();
    QSettings settings (PROGRAM_COMP, PROGRAM_NAME);    
    restoreGeometry(settings.value("MainWindow/geometry").toByteArray());
    settings.beginGroup("profileList");
    QStringList list = settings.childGroups();
    profiles.clear();
    Profile * newProfile = 0;
    qDebug() << ">> Restore Profiles Count =" << list.count();
    for (int i = 0; i < list.count();i ++){
	newProfile = new Profile();
	newProfile -> setId(list[i]);
	newProfile -> restore(settings);
	profiles << newProfile;
    }
    settings.endGroup();
    
    settings.beginGroup("Global");
    Options::getGlobalOptions()->restore(settings);
    settings.endGroup();
}

void MainWindow::on_actionConfigure_triggered(){
    DEBUG_F();
    ConfigureDialog configureDialog(&profiles, this);
    configureDialog.exec();
    writeSettings();
    mainProcess();
}

void MainWindow::mainProcess(){
    serverModel->clear();
    profiles.removeAll(0);
    qDebug() << ">> Now we have" << profiles.size() << "profiles.";
    foreach(Profile * profile, profiles){
	connect (profile->getBBS(), SIGNAL(refreshFinished(bool)), serverModel, SLOT(refresh(bool)));
	connect (profile->getBBS(), SIGNAL(newStatus(int, QString)), this, SLOT(updateStatusBar(int, QString)));
	profile->setTimer(&gTimer);
	if (profile->checkLogin() || profile->getOption("isAutoLogin"))
	    profile->getBBS()->start();
	serverModel->addSource(profile->getBBS());
    }
    boardList->expandAll();
    //qDebug() << "mainProcess() ends.";
}

///------------------------------- Beautiful Splitter LIne ----------------------------------
/// defines for the board model
///BEGIN bbsModel
bbsModel::bbsModel(QObject *parent ) : QAbstractItemModel(parent) {
    //boardPool = 0;
}

void bbsModel::addSource (BBS * bbs){
    pool.append(bbs);
    reset();
}

void bbsModel::clear(){
    pool.clear();
}

void bbsModel::refresh(bool){
    qDebug() << ">> TODO: refresh the bbsModel's data.";
}

int bbsModel::columnCount(const QModelIndex &/*parent*/) const{
    return 1;
}

bool bbsModel::showAll(baseOnProfile * p) const{
    return !p->getProfile()->getOption("isFavoriteMode");
}

QModelIndex bbsModel::index(int row, int column, const QModelIndex &parent) const{
    if (column > 0) return QModelIndex();
    if (!parent.isValid()){		// return a bbs item
	if (row < pool.count())
	    return createIndex(row, column, pool.at(row));
	else return QModelIndex();
    }
    
    baseOnProfile * p = static_cast<baseOnProfile *> (parent.internalPointer());
    BBS * bbs = p->getProfile()->getBBS();
    if (p != bbs) return QModelIndex();

    bool sign = showAll(p);
    if (sign && row < bbs->boardPool.count())
	return createIndex(row, column, bbs->boardAt(row));
    else if( !sign && row < p->getProfile()->getFavoriteBoard()->count())
	return createIndex(row, column, p->getProfile()->getFavoriteBoard()->at(row));
    else
	return QModelIndex();
}

QModelIndex bbsModel::parent(const QModelIndex & child) const{
    baseOnProfile * p = static_cast<baseOnProfile *>(child.internalPointer());
    BBS * bbs = p->getProfile()->getBBS();
    if (bbs == p)	//the 'child' is BBS,no parent
	return QModelIndex();
    else		// otherwise the 'child' is Board
	return createIndex(pool.indexOf(bbs), 0, bbs);
}

QVariant bbsModel::data(const QModelIndex &index, int role) const{
    if (!index.isValid() )	return QVariant();
    baseOnProfile * p = static_cast<baseOnProfile *>(index.internalPointer());
    BBS * bbs = p->getProfile()->getBBS();
    if (role == Qt::DisplayRole){
	if (p == bbs)
	    return bbs->display();		//bbs
	else{
	    Board * board = static_cast<Board *>(p);
	    return board->display();
	}
    }
    else if (role == Qt::TextAlignmentRole)
	return int(Qt::AlignCenter|Qt::AlignVCenter);
    else
	return QVariant();
}

int bbsModel::rowCount(const QModelIndex &parent) const{
    if (!parent.isValid())	// Top-level
	return pool.count();
    baseOnProfile * p = static_cast<baseOnProfile *>(parent.internalPointer());
    BBS * bbs = p->getProfile()->getBBS();
    if (bbs == p){
	if (showAll(p))
	    return bbs->boardPool.count();
	else
	    return p->getProfile()->getFavoriteBoard()->count();	    
    }
    else
	return 0;
}

Board * bbsModel::index2Board(const QModelIndex & index){
    if (!index.isValid()) return 0;
    baseOnProfile * p = static_cast<baseOnProfile *>(index.internalPointer());
    BBS * bbs = p->getProfile()->getBBS();
    if (p == bbs) return 0;
    return static_cast<Board *> (index.internalPointer());
}

Profile * bbsModel::index2Profile(const QModelIndex & index){
    if (!index.isValid()) return 0;
    baseOnProfile * p = static_cast<baseOnProfile *>(index.internalPointer());
    return p->getProfile();
}
///END bbsModel

